2016-09-08 22 views
6

最近、C#プロジェクトの1つであるMoqライブラリ(4.5.21)の非常に興味深い動作を発見しました。以下は私がテストしようとしているクラスです。Moqを使って異なる状態のオブジェクトを使ってメソッド呼び出しを確認する

Moq.MockException: 
Expected invocation on the mock once, but was 0 times: x => x.UpdateOrderAsync(It.Is<Order>(o => o.State == "new")) 


Configured setups: 
x => x.UpdateOrderAsync(It.Is<Order>(o => o.State == "new")), Times.Once 
x => x.UpdateOrderAsync(It.Is<Order>(o => o.State == "open")), Times.Once 

Performed invocations: 
IOrderService.UpdateOrderAsync(Order<State:open>) 
IOrderService.UpdateOrderAsync(Order<State:open>) 

は私が期待する私はVerifyできる方法が毎回Onceと呼ばれていたということobjectと:私は出力次取得

[TestMethod] 
public async Task TestMethod() 
{ 
    var mock = new Mock<IOrderService>(); 
    await new Program().RunAsync(mock.Object); 

    mock.Verify(x => x.UpdateOrderAsync(It.Is<Order>(o => o.State == "new")), Times.Once); 
    mock.Verify(x => x.UpdateOrderAsync(It.Is<Order>(o => o.State == "open")), Times.Once); 
} 

:以下

public class Order 
{ 
    public string State { get; set; } 
} 

public interface IOrderService 
{ 
    Task UpdateOrderAsync(Order order); 
} 

public class Program 
{ 
    public async Task RunAsync(IOrderService orderService) 
    { 
     var order = new Order(); 

     order.State = "new"; 
     await orderService.UpdateOrderAsync(order); 

     order.State = "open"; 
     await orderService.UpdateOrderAsync(order); 
    } 
} 

は私のTestClassをあります異なった Stateと。私は何が間違っているのだろうか?

ありがとうございました!

答えて

2

は、この時点で最初に確認しますので、基本的にそれはだthis post

と非常によく似ていますが呼び出され、モックは(特定の呼び出しのために)保持している参照は、そのStateプロパティは、単に(「オープン」に変更されてきました2番目の呼び出しの前に)。これは、Orderクラスを構造体に変更して、モックがオブジェクト自体への参照ではなくオブジェクトのコピーをキャプチャすることを確認することで証明できます。

EDIT:完全な答えを期すため と上記ポストが廃止されました期待し使用しています、ここで合格テストです:

var mock = new Mock<IOrderService>(MockBehavior.Loose); 

var newCalled = false; 
var openCalledBeforeNew = false; 

mock.Setup(x => x.UpdateOrderAsync(It.Is<Order>(o => o.State == "new"))).Callback(() => newCalled = !openCalledBeforeNew).Returns(Task.FromResult((object)null)); 
mock.Setup(x => x.UpdateOrderAsync(It.Is<Order>(o => o.State == "open"))).Callback(() => openCalledBeforeNew = newCalled).Returns(Task.FromResult((object)null)); 

await new Program().RunAsync(mock.Object); 

Assert.IsTrue(newCalled); 
Assert.IsTrue(openCalledBeforeNew); 
2

セットアップは、コールバックを使用するためのモック。コールバックの中にここで完全なテスト方法

[TestMethod] 
public async Task TestMethod1() 
{ 

    var mock = new Mock<IOrderService>(); 

    Order o1 = new Order() { State = "new" }; 

    int countOrderStateNew = 0; 
    int countOrderStateOpen = 0; 

    mock.Setup(a => a.UpdateOrderAsync(It.Is<Order>(o => o.State == "new"))) 
     .Returns(Task.Factory.StartNew(() => { })) 
     .Callback(() => countOrderStateNew++); 
    mock.Setup(a => a.UpdateOrderAsync(It.Is<Order>(o => o.State == "open"))) 
     .Returns(Task.Factory.StartNew(() => { })) 
     .Callback(()=> countOrderStateOpen++); 

    await new Program().RunAsync(mock.Object); 

    Assert.AreEqual(1, countOrderStateNew); 
    Assert.AreEqual(1, countOrderStateOpen); 


} 
があるメソッドが

mock.Setup(a => a.UpdateOrderAsync(It.Is<Order>(o => o.State == "new"))) 
    .Returns(Task.Factory.StartNew(() => { })) 
    .Callback(() => countOrderStateNew++); 

と呼ばれた回数をカウント

関連する問題