2017-06-06 5 views
1

私はMoqで混乱しています。私は何が間違っているのか分かりません。UnitTests - Moq - Setup()のParameterと一致するMoqからオブジェクトを返す方法

ILeadStorageServiceに依存するLeadServiceをテストしたいと思います。そのようにMoqを設定したい - セットアップで渡されたGUIDと一致するオブジェクトを返します。

問題はMoq Setup/Returns行にあります。なぜなら、依存オブジェクトをその実際のインスタンスに置き換えると、テストは合格しますが、それは完全に間違っているからです。 Dependent StorageではなくLeadServiceだけをテストしたいと思っています。

public LeadService(IConfigurationDbContext configurationDbContext, 
         ILeadStorageService leadStorageService, 
         ILeadDeliveryService deliveryService) 
    { 
     this.configurationDbContext = configurationDbContext; 
     this.leadStorageService = leadStorageService; 
     this.deliveryService = deliveryService; 

    } 

テスト済みの方法テストの準備で、その後

 public TestLeadResponse ProcessTestLead(TestLeadRequest request) 
     { 
     var response = new TestLeadResponse() 
     { 
      Status = TestLeadStatus.Ok 
     }; 

     try 
     { 
      var lead = leadStorageService.Get(request.LeadId); 
      if (lead == null) 
      { 
       throw new LeadNotFoundException(request.LeadId); 
      } 

      var buyerContract = 
       configurationDbContext.BuyerContracts.SingleOrDefault(bc => bc.Id == request.BuyerContractId); 
      if (buyerContract == null) 
      { 
       throw new BuyerContractNotFoundException(request.BuyerContractId); 
      } 

      response.DeliveryEntry = deliveryService.DeliverLead(lead, buyerContract); 
     } 
     catch (LeadNotFoundException e) 
     { 
      response.Status = TestLeadStatus.LeadNotFound; 
      response.StatusDescription = e.Message; 
     } 
     catch (BuyerContractNotFoundException e) 
     { 
      response.Status = TestLeadStatus.BuyerContractNotFound; 
      response.StatusDescription = e.Message; 
     } 

     return response; 
    } 

[TestInitialize] 
    public void Initialize() 
    { 
     _leadIdStr = "2c3ac0c0-f0c2-4eb0-a55e-600ae3ada221"; 

     _dbcontext = new ConfigurationDbContext(); 
     _lead = PrepareLeadObject(); 
     _buyerContract = PrepareBuyerContractObject(Id : 1, BuyerContractId : 1, BuyerTag: "GAME"); 
     _leadDeliveryMock = new Mock<ILeadDeliveryService>(); 
     _leadStorageMock = new Mock<ILeadStorageService>(); 
     _leadStorageService = new LeadStorageService("LeadGeneration_Dev"); 

    } 

    private Lead PrepareLeadObject() 
    { 
     var lead = new Lead() {CountryId = 1, Country = "NL", Id = Guid.Parse(_leadIdStr)}; 
     return lead; 

    } 

とテスト自体:

[TestMethod] 
    public void LeadServiceTest_ProcessTestLeadWithWrongBuyerContractIDThrowsBuyerContractNotFoundException() 
    { 
     _leadDeliveryMock 
      .Setup(methodCall => methodCall.DeliverLead(_lead, _buyerContract)) 
      .Returns<LeadDeliveryEntry>((r) => PrepareLeadDeliveryEntry()); 

     // here is the problem!!!! 
     _leadStorageMock.Setup(mc => mc.Get(_leadId)).Returns((Lead l) => PrepareLeadObject()); 

     //if i change to real object - test passes 
     //_service = new LeadService(_dbcontext, _leadStorageService, _leadDeliveryMock.Object); 
     _service = new LeadService(_dbcontext, _leadStorageMock.Object, _leadDeliveryMock.Object); 

     var response = _service.ProcessTestLead(new TestLeadRequest() { BuyerContractId = int.MaxValue, LeadId = _leadId }); 

     Assert.IsNotNull(response); 
     Assert.AreEqual(response.Status, TestLeadStatus.BuyerContractNotFound); 

    } 

代わりの期待リターン - 私は例外が発生しました: ArgumentException

_leadStorageMock.Setup()には何が欠けていますか?

答えて

4

Returns拡張メソッドは、あなたが模擬しているメソッドと同じパラメータを持つデリゲートを受け入れます。これらの引数は、擬似メソッドの呼び出し中に委譲先に渡されます。だからではなく、Lead対象の、あなたはmc.Getメソッドに渡される引数を取得します - リードID:

_leadStorageMock.Setup(mc => mc.Get(_leadId)) 
     .Returns((Guid leadId) => PrepareLeadObject()); 

チェック値を返すときに、呼び出しに引数へのアクセスに関連QuickStartセクションを。


引数として値関数を受け入れるReturns拡張メソッドの束があることに注意してください:あなたはそれらの値の関数は、モックメソッドから返される値を計算する見ることができるように

Returns<T>(Func<T, TResult> valueFunction); 
Returns<T1, T2>(Func<T1, T2, TResult> valueFunction); 
Returns<T1, T2, T3>(Func<T1, T2, T3, TResult> valueFunction); 
// etc 

が、しかし、それらはすべて異なる数の引数(最大16)を受け取ります。これらの引数は、あなたが嘲笑しているメソッドの引数と正確に一致し、擬似メソッドの呼び出し中にvalueFunctionに渡されます。あなたは二つの引数でいくつかの機能をからかっているのであれば、それに対応する拡張機能を使用する必要があります。

mock.Setup(m => m.Activate(It.IsAny<int>(), It.IsAny<bool>()) 
    .Returns((int i, bool b) => b ? i : 0); // Func<T1, T2, TResult> 
+1

感謝を!それほど明白ではなかった。 – Lightning3

関連する問題