c# msbuild msbuild-task invalidoperationexception

c# - Prueba unitaria MSBuild Tarea personalizada sin error "La tarea intentó iniciar sesión antes de que se inicializara"



msbuild-task invalidoperationexception (6)

He escrito algunas tareas personalizadas de MSBuild que funcionan bien y se usan en nuestro proceso de compilación CruiseControl.NET.

Estoy modificando uno y deseo probarlo en una unidad llamando al método Execute () de la tarea.

Sin embargo, si encuentra una línea que contiene

Log.LogMessage("some message here");

arroja una InvalidOperationException:

La tarea intentó iniciar sesión antes de que se inicializara. El mensaje fue ...

¿Alguna sugerencia? (En el pasado, tenía métodos estáticos internos mayormente probados en unidades en mis tareas personalizadas para evitar tales problemas).


Si ha implementado la interfaz ITask, deberá inicializar la clase Log usted mismo.

De lo contrario, simplemente debe heredar de Tarea en Microsoft.Build.Utilities.dll que implementa ITask y hace mucho trabajo por usted.

Aquí está la página de referencia para construir una tarea personalizada, explica bastante.

Crear una referencia de tarea MSBuild personalizada

También vale la pena echar un vistazo

Cómo depurar una tarea personalizada de MSBuild

Aparte de eso, podría publicar el XML de MSBuild que está utilizando para llamar a su tarea personalizada. El código en sí sería obviamente la mejor ayuda :-)


Descubrí que la instancia de registro no funciona a menos que la tarea se esté ejecutando dentro de msbuild, por lo que generalmente cierro mis llamadas a Log, luego verifico el valor de BuildEngine para determinar si estoy ejecutando dentro de msbuild. Como a continuación.

Tim

private void LogFormat(string message, params object[] args) { if (this.BuildEngine != null) { this.Log.LogMessage(message, args); } else { Console.WriteLine(message, args); } }


Debe establecer la propiedad .BuildEngine de la tarea personalizada a la que está llamando.

Puede establecerlo en el mismo BuildEngine que está utilizando su tarea actual para incluir la salida sin problemas.

Task myCustomTask = new CustomTask(); myCustomTask.BuildEngine = this.BuildEngine; myCustomTask.Execute();


Comentario de @Kiff en mock / stub IBuildEngine es una buena idea. Aquí está mi FakeBuildEngine. Se proporcionan ejemplos de C # y VB.NET.

VB.NET

Imports System Imports System.Collections.Generic Imports Microsoft.Build.Framework Public Class FakeBuildEngine Implements IBuildEngine // It''s just a test helper so public fields is fine. Public LogErrorEvents As New List(Of BuildErrorEventArgs) Public LogMessageEvents As New List(Of BuildMessageEventArgs) Public LogCustomEvents As New List(Of CustomBuildEventArgs) Public LogWarningEvents As New List(Of BuildWarningEventArgs) Public Function BuildProjectFile( projectFileName As String, targetNames() As String, globalProperties As System.Collections.IDictionary, targetOutputs As System.Collections.IDictionary) As Boolean Implements IBuildEngine.BuildProjectFile Throw New NotImplementedException End Function Public ReadOnly Property ColumnNumberOfTaskNode As Integer Implements IBuildEngine.ColumnNumberOfTaskNode Get Return 0 End Get End Property Public ReadOnly Property ContinueOnError As Boolean Implements IBuildEngine.ContinueOnError Get Throw New NotImplementedException End Get End Property Public ReadOnly Property LineNumberOfTaskNode As Integer Implements IBuildEngine.LineNumberOfTaskNode Get Return 0 End Get End Property Public Sub LogCustomEvent(e As CustomBuildEventArgs) Implements IBuildEngine.LogCustomEvent LogCustomEvents.Add(e) End Sub Public Sub LogErrorEvent(e As BuildErrorEventArgs) Implements IBuildEngine.LogErrorEvent LogErrorEvents.Add(e) End Sub Public Sub LogMessageEvent(e As BuildMessageEventArgs) Implements IBuildEngine.LogMessageEvent LogMessageEvents.Add(e) End Sub Public Sub LogWarningEvent(e As BuildWarningEventArgs) Implements IBuildEngine.LogWarningEvent LogWarningEvents.Add(e) End Sub Public ReadOnly Property ProjectFileOfTaskNode As String Implements IBuildEngine.ProjectFileOfTaskNode Get Return "fake ProjectFileOfTaskNode" End Get End Property End Class

DO#

using System; using System.Collections.Generic; using Microsoft.Build.Framework; public class FakeBuildEngine : IBuildEngine { // It''s just a test helper so public fields is fine. public List<BuildErrorEventArgs> LogErrorEvents = new List<BuildErrorEventArgs>(); public List<BuildMessageEventArgs> LogMessageEvents = new List<BuildMessageEventArgs>(); public List<CustomBuildEventArgs> LogCustomEvents = new List<CustomBuildEventArgs>(); public List<BuildWarningEventArgs> LogWarningEvents = new List<BuildWarningEventArgs>(); public bool BuildProjectFile( string projectFileName, string[] targetNames, System.Collections.IDictionary globalProperties, System.Collections.IDictionary targetOutputs) { throw new NotImplementedException(); } public int ColumnNumberOfTaskNode { get { return 0; } } public bool ContinueOnError { get { throw new NotImplementedException(); } } public int LineNumberOfTaskNode { get { return 0; } } public void LogCustomEvent(CustomBuildEventArgs e) { LogCustomEvents.Add(e); } public void LogErrorEvent(BuildErrorEventArgs e) { LogErrorEvents.Add(e); } public void LogMessageEvent(BuildMessageEventArgs e) { LogMessageEvents.Add(e); } public void LogWarningEvent(BuildWarningEventArgs e) { LogWarningEvents.Add(e); } public string ProjectFileOfTaskNode { get { return "fake ProjectFileOfTaskNode"; } } }


Yo tuve el mismo problema. Lo solucioné apagando el motor de construcción. Al igual que (AppSettings es el nombre de tarea de MsBuild):

using Microsoft.Build.Framework; using NUnit.Framework; using Rhino.Mocks; namespace NameSpace { [TestFixture] public class Tests { [Test] public void Test() { MockRepository mock = new MockRepository(); IBuildEngine engine = mock.Stub<IBuildEngine>(); var appSettings = new AppSettings(); appSettings.BuildEngine = engine; appSettings.Execute(); } } }


En ensamble System.Web en el namespace de namespace System.Web.Compilation es una clase MockEngine que implementa la interface IBuildEngine de una manera que describe a Tim Murphy.