2016-06-08 10 views
1

Ich schreibe einige Komponententests für Code, der bereits geschrieben wurde. Ich geriet in eine Situation, auf die ich überraschenderweise noch nicht gestoßen bin.Mocking Service-Kanäle

Kurz gesagt, ich muss einen Controller testen, der eine Dienstabhängigkeit über DI aufnimmt, und in der Aktion Index wird eine Methode aufgerufen, um Daten für die Ansicht zurückzugeben.

Mein Problem ist, dass ich nicht scheinen kann, die Dienstabhängigkeit zu verspotten. Ich habe versucht, ein bisschen zu suchen, konnte aber nichts finden, das direkt mit meinem Problem (oder meinem Unverständnis) zu tun hatte.

Im Folgenden ist ein Beispiel für die Steuerung:

public partial class SomeController : Controller 
{ 
    private readonly IServiceChannel<ISomeService> _someChannel; 

    public SomeController(IServiceChannel<ISomeService> someChannel) 
    { 
     _someChannel= someChannel; 
    } 

    public virtual ActionResult Index() 
    { 
     var response = _someChannel.Fetch(someService => someService .GetSomeData(
      new GetSomeDataRequest 
      { 
       Id= StaticData.Id, 
       All = true 
      } 
     )); 

     var model = new IndexViewModel 
     { 
      AllData= response.AllData 
     }; 

     return View(model); 
    } 
} 

Wie Sie sehen können, DI spritzt eine Instanz von IServiceChannel, die eine „Fetch“ -Methode hat. Diese Methode gibt Ihnen dann Zugriff auf ISomeService und von dort können Sie jede Methode auf der Schnittstelle mit den erforderlichen Parametern aufrufen.

ich versuchte, einen Test, um diesen mit der folgenden Logik zu schreiben:

[TestFixture] 
public class SomeControllerTests 
{ 
    private IServiceChannel<ISomeService> _someChannel; 
    [SetUp] 
    public void Setup() 
    { 
     var someChannelMoc = new Mock<IServiceChannel<ISomeService>>(); 
     someChannelMoc.Setup(
      i => i.Fetch(service => service.GetSomeData(It.IsAny<GetSomeDataRequest>()))) 
      .Returns(new GetSomeDataResponse()); 

     _someChannel= someChannelMoc.Object; 
    } 

    [Test] 
    public void IndexTest() 
    { 
     var controller = new SomeController(_someChannel); 
     var result = controller.Index(); 
     Assert.IsNotNull(result); 
    } 
} 

Das alles gut baut, aber wenn die Testläufe ich die folgende Fehlermeldung angezeigt:

SetUp : System.NotSupportedException : Unsupported expression: service => service.GetSomeData(IsAny()) at Moq.MatcherFactory.CreateMatcher(Expression expression, Boolean isParams) at Moq.MethodCall..ctor(Mock mock, Condition condition, Expression originalExpression, MethodInfo method, Expression[] arguments) at Moq.MethodCallReturn..ctor(Mock mock, Condition condition, Expression originalExpression, MethodInfo method, Expression[] arguments) at Moq.MethodCallReturn 2..ctor(Mock mock, Condition condition, Expression originalExpression, MethodInfo method, Expression[] arguments) at Moq.Mock.<>c__DisplayClass1c 2.b__1b() at Moq.PexProtector.Invoke[T](Func 1 function) at Moq.Mock.Setup[T,TResult](Mock 1 mock, Expression 1 expression, Condition condition) at Moq.Mock 1.Setup[TResult](Expression`1 expression) at MyProj.Tests.Controllers.SomeControllerTests.Setup() in path location

Jede mögliche Hilfe sehr geschätzt werden!

Antwort

1

Nun, nach einiger Arbeit, ich denke, Ich fand es heraus. Ich brauchte die Funktionsparameter in meiner IServiceChannel Implementierung zum Spiel:

public TResult Fetch<TResult>(Func<T, TResult> block) 
{ ... } 

So jetzt mein Test-Setup wie folgt aussehen geändert:

var someChannelMoc = new Mock<IServiceChannel<ISomeService>>(); 
      someChannelMoc.Setup(i => i.Fetch(It.IsAny<Func<ISomeService,GetSomeDataResponse>>())) 
       .Returns(()=>new GetSomeDataResponse{AllData= new List<Data>()}); 

      _someChannel = someChannelMoc.Object; 

Aus Gründen der etwas besser, ich werde halten Ich werde dies als beantwortet markieren, um zu sehen, ob etwas Besseres kommt, da ich den Eingabeparameter für die Funktion nicht spezifizieren kann. Das ist kein Problem für mich, aber es könnte für jemanden in der Zukunft sein.