Soru MSBuild Custom Task, "Görev başlatılmadan önce günlüğe kaydetme girişiminde bulunulmadı" hatası olmadan hata verdi


İyi çalışan ve CruiseControl.NET oluşturma işlemimizde kullandığımız birkaç MSBuild özel görevi yazdım.

Birini değiştiriyorum ve Birim'in Execute () yöntemini çağırarak birimi test etmeyi istiyorum.

Bununla birlikte, eğer bir çizgi ile karşılaşırsa

Log.LogMessage("some message here");

InvalidOperationException atar:

Görev başlatılmadan önce günlüğe kaydetmeye çalıştı. Mesaj ...

Baska öneri? (Geçmişte, bu tür sorunlardan kaçınmak için özel görevlerimde çoğunlukla ünite tarafından test edilen Dahili statik yöntemlere sahibim.)


25
2017-11-04 04:05


Menşei


Şimdi bunun için bazı özel görevlerde bununla karşılaştım - Branstar'ın cevabı doğruydu! Sadece çağrılan görev üzerinde BuildEngine ayarlayın. - Jarrod Dixon♦


Cevaplar:


Aramakta olduğunuz özel görevin .BuildEngine özelliğini ayarlamanız gerekir.

Mevcut görevinizin çıktıyı kesintisiz olarak dahil etmek için kullandığınız BuildEngine ile aynı şekilde ayarlayabilirsiniz.

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

25
2017-11-20 14:12



Bu tam olarak ihtiyacım olan şeydi - teşekkürler! - Jarrod Dixon♦
Soru bir birim testi bağlamında olduğundan, alternatif olarak BuildEngine özelliğini IBuildEngine arabirimini uygulayan bir sahte / saplama nesnesine ayarlayabileceğinizi de eklerim. - Chris Staley


Görev, msbuild içinde çalışmadığı sürece günlük örneğinin çalışmadığını fark ettim, bu yüzden genellikle çağrılarımı Log'a kaydırırım, sonra msbuild içinde çalışıp çalışmadığımı belirlemek için BuildEngine değerini kontrol et. Aşağıda olduğu gibi.

Tim

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

14
2017-11-13 17:57





Eğer ITask arayüzünü uyguladıysanız, Log sınıfını kendiniz başlatmanız gerekecektir.

Aksi halde, Görev Microsoft.Build.Utilities.dll içinde Bu uygular ITask ve bacağınız için çok çalışıyor.

İşte özel bir görev oluşturmak için referans sayfası, oldukça fazla açıklıyor.

Özel bir MSBuild görev referansı oluşturma

Ayrıca bir bakmaya değer

Özel bir MSBuild görevinde hata ayıklama

Diğer sonra, özel görevinizi çağırmak için kullandığınız MSBuild XML dosyasını gönderebilirsiniz. Kod kendisi açıkça en yardım :-) olurdu


7
2017-11-08 12:12



+1 ... güzel linkler - alexandrul


Mock / saplama IBuildEngine üzerinde @Kiff yorum iyi bir fikirdir. İşte benim FakeBuildEngine. C # ve VB.NET örnekleri sağladı.

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

C #

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"; }
    }

}

7
2018-04-10 10:09



Sadece alaycı bir çerçeve kullanmalı. NSubstitute'de şöyle olurdu: var engine = Substitute.For <IBuildEngine> (); - justin.m.chase
Doğru, sadece InvalidOperationExceptionsomut bir uygulamaya gerek yoktur. Örnek boş olmadığı sürece, InvalidOperationException. Moq için olurdu myCustomTask.BuildEngine = new Mock<IBuildEngine>().Object;. Daha az hata için daha az kod :) - mikegradek
@perropicante True Moq kullanılmış olabilir. O zamanlar IBuildEngine'e ihtiyaç duyulan birçok testim vardı ve somut bir uygulamanın kullanılması daha kolaydı ve testleri daha kolay okumuştur. - Tim Murphy


Bende aynı problem vardı. Yapı motorunu kovalı olarak çözdüm. Öyle (AppSettings MsBuild Görev Adıdır):

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();
        }
    }
}

1
2018-03-04 22:14





Mecliste System.Web içinde namespace  System.Web.Compilation bir sınıf MockEngine hangi uygular IBuildEngine  interface Tim Murphy'yi tanımlayan bir şekilde.


0
2017-09-01 07:47



... Jack'in inşa ettiği evde. - teo van kot