我正在嘗試學習Rhino Mocks AAA語法,並且我無法斷言某個方法(使用任何參數值)被調用。我使用Machine.Specifications作爲我的測試框架。如何使用RhinoMocks AssertWasCalled使用三種不同類型的通用方法?
這種特殊的方法是通用的,我想確保它有三種不同的類型被稱爲三次。
repo.Save<T1>(anything), repo.Save<T2>(anything), and repo.Save<T3>(anything)
我將每種類型的函數都存起來。但是我得到一個有趣的結果。 (下)
[Subject("Test")]
public class When_something_happens_with_constraint
{
static IRepository repo;
static TestController controller;
static ActionResult result;
Establish context =() =>
{
repo = MockRepository.GenerateMock<IRepository>();
controller = new TestController(repo);
repo.Stub(o => o.Save<Something>(Arg<Something>.Is.Anything));
repo.Stub(o => o.Save<SomethingElse>(Arg<SomethingElse>.Is.Anything));
repo.Stub(o => o.Save<AnotherOne>(Arg<AnotherOne>.Is.Anything));
};
//post data to a controller
Because of =() => { result = controller.SaveAction(new SomethingModel() { Name = "test", Description = "test" }); };
//controller constructs its own something using the data posted, then saves it. I want to make sure three calls were made.
It Should_save_something =() => repo.AssertWasCalled(o => o.Save<Somethign>(Arg<Something>.Is.Anything));
It Should_save_something_else =() => repo.AssertWasCalled(o => o.Save<SomethingElse>(Arg<SomethingElse>.Is.Anything));
It Should_save_another_one =() => repo.AssertWasCalled(o => o.Save<AnotherOne>(Arg<AnotherOne>.Is.Anything));
}
結果是兩個例外和通過。
第一調用拋出:
System.InvalidOperationException:沒有期望是設置要被驗證,確保在該操作的方法調用是虛擬(C#)/可重寫(VB.Net)方法調用
第二個拋出:
System.InvalidOperationException:使用ARG僅在模擬方法調用,同時記錄。預期有1個參數,其中2個已被定義。
第三個通過...有些奇怪的原因。
我也嘗試使用GenerateMock()與期望在我的設置以及與存根使用GenerateStub()。兩者都以完全相同的結果結束。我必須做錯事。
我使用: MachineSpec 0.3.0.0和3.6.0.0 RhinoMocks
任何想法?
-----固定----------
下面是完整的(工作版本)與李的幫助。我正在使用一個額外的(非linq)圖層。我的實際問題是,我的一個測試在脫機實際代碼中重新使用了錯誤的lambda變量。 It Should_do_something =()=> repo.AssertWasCalled(o =>repo .Save(data)); // bad lambda
所以這裏有一個正確的測試參考樣本。
using System;
using System.Linq;
using System.Collections.Generic;
using Machine.Specifications;
using Rhino.Mocks;
namespace OnlineTesting.Specifications
{
public interface Repository
{
void Save<T>(T data);
IQueryable<T> All<T>();
}
public interface Service
{
void SaveItem(Item data);
void SaveAnotherItem(AnotherItem data);
void SaveOtherItem(OtherItem data);
List<Item> GetItems();
List<AnotherItem> GetAnotherItems();
List<OtherItem> GetOtherItems();
}
public class ConcreteService : Service
{
Repository repo;
public ConcreteService(Repository repo)
{
this.repo = repo;
}
public void SaveItem(Item data)
{
repo.Save(data);
}
public void SaveAnotherItem(AnotherItem data)
{
repo.Save(data);
}
public void SaveOtherItem(OtherItem data)
{
repo.Save(data);
}
public List<Item> GetItems()
{
return repo.All<Item>().ToList();
}
public List<AnotherItem> GetAnotherItems()
{
return repo.All<AnotherItem>().ToList();
}
public List<OtherItem> GetOtherItems()
{
return repo.All<OtherItem>().ToList();
}
}
public class Item
{
public int Id { get; set; }
}
public class OtherItem
{
}
public class AnotherItem
{
}
public class When_something_else_happens
{
Establish context =() =>
{
_repository = MockRepository.GenerateMock<Repository>();
_service = new ConcreteService(_repository);
_controller = new TestController(_service);
_repository.Stub(o => o.Save<Item>(Arg<Item>.Is.Anything)).WhenCalled(
new Action<MethodInvocation>((o) =>
{
var data = o.Arguments.FirstOrDefault() as Item;
if (data != null && data.Id == 0)
data.Id++;
}));
};
Because of =() => _controller.DoSomethingElse();
It should_save_the_first_thing =() =>
_repository.AssertWasCalled(repo => repo.Save(Arg<Item>.Is.Anything));
It should_save_the_other_thing =() =>
_repository.AssertWasCalled(repo => repo.Save(Arg<OtherItem>.Is.Anything));
It should_save_the_last_thing =() =>
_repository.AssertWasCalled(repo => repo.Save(Arg<AnotherItem>.Is.Anything));
static Repository _repository;
static TestController _controller;
static Service _service;
}
public class TestController
{
readonly Service _service;
public TestController(Service service)
{
_service = service;
}
public void DoSomethingElse()
{
_service.SaveItem(new Item());
_service.SaveOtherItem(new OtherItem());
_service.SaveAnotherItem(new AnotherItem());
}
}
}
另外...我不能在調用之前設置參數,因爲控制器操作會構造一個新對象並將其傳遞給存儲庫。所以我使用Arg。任何事情。我只是想確保repo.save被稱爲特定類型。 –
Nathan
2010-11-19 16:01:34