2011-06-27 189 views
2

我正在使用生成器模式爲控制器生成viewmodels,並且當我嘗試單元測試我的控制器時,發現自己無法這樣做。 Moq抱怨。Moq單元測試生成器模式

不確定這是Moq限制還是我自己的限制和無知。

這是我的控制器是什麼樣子:

public class OutletController : Controller 
{ 
    private readonly IOutletViewModelBuilder _builder; 

    public OutletController(IOutletViewModelBuilder builder) 
    { 
     this._builder = builder; 
    } 


    public ActionResult Edit(int id) 
    { 
     OutletViewModel viewModel = this._builder.WithOutlet(id).WithCountryList().Build(); 

     return View(viewModel); 
    } 
} 

我試圖嘲弄IOutletViewModelBuilder對象,但是這是我得到:

[Test] 
public void DummyTest() 
{ 
    Mock<IOutletViewModelBuilder> mockBuilder = new Mock<IOutletViewModelBuilder>(); 
    // (1) // mockBuilder.Setup(m => m.WithOutlet(It.IsAny<int>())).Returns(mockBuilder.Object); 
    // (2) //mockBuilder.Setup(m => m.WithOutlet(It.IsAny<int>())).Returns(mockBuilder); 

    // (3) // mockBuilder.Setup(m => m.WithOutlet(It.IsAny<int>()).WithCountryList().Build()).Returns(new OutletViewModel()); 

    OutletController controller = new OutletController(mockBuilder.Object); 
    ActionResult result = controller.Edit(1); 

    Assert.IsTrue(true); 
} 

(1)給我以下錯誤突出顯示(mockBuilder.Object)

無法解析方法'返回(ViewModelBuilders.Builders.IOutletViewModelBuilder)',考生是:

Moq.Language.Flow.IReturnsResult<ViewModelBuilders.Builders.IOutletViewModelBuilder> Returns(System.Func<ViewModelBuilders.Builder.IOutletViewModelBuilder>) (in interface IReturns<IOutletViewModelBuilder,OutletViewModelBuilder>) 
Moq.Language.Flow.IReturnsResult<ViewModelBuilders.Builders.IOutletViewModelBuilder> Returns(ViewModelBuilders.Builders.OutletViewModelBuilder) (in interface IReturns<IOutletViewModelBuilder,OutletModelBuilder>) 

(2)引發以下錯誤:

無法解析法 '返回(Moq.Mock)',考生是:

Moq.Language.Flow.IReturnsResult<ViewModelBuilders.Builders.IOutletViewModelBuilder> Returns(System.Func<ViewModelBuilders.Builders.OutletViewModelBuilder>) (in interface IReturns<IOutletViewModelBuilder,OutletViewModelBuilder>) 
Moq.Language.Flow.IReturnsResult<ViewModelBuilders.Builders.IOutletViewModelBuilder> Returns(ViewModelBuilders.Builders.OutletViewModelBuilder) (in interface IReturns<IOutletViewModelBuilder,OutletViewModelBuilder>) 

(3)不會拋出一個編譯時錯誤,但運行時一個:

System.NotSupportedException : Invalid setup on a non-virtual (overridable in VB) member: m => m.WithOutlet(It.IsAny<Int32>()).WithCountryList().Build() 
at Moq.Mock.ThrowIfCantOverride(Expression setup, MethodInfo method) 
at Moq.Mock.<>c__DisplayClass1c`2.<Setup>b__1b() 
at Moq.Mock.Setup(Mock mock, Expression`1 expression, Func`1 condition) 
at ViewModelBuilderTests.OutletControllerTest.DummyTest() 

任何幫助將不勝感激。單元測試這個方法應該不是很難嗎?

下面你可以看到Builder對象,以防你需要看到實現。

public class OutletViewModelBuilder 
{ 
    private readonly IRepository _repository; 
    private OutletViewModel _viewModel; 

    public OutletViewModelBuilder(IRepository repository) 
    { 
     this._repository = repository; 
     this._viewModel = new OutletViewModel(); 
    } 

    public OutletViewModel Build() 
    { 
     return this._viewModel; 
    } 

    public OutletViewModelBuilder WithOutlet(int outletId) 
    { 
     this._viewModel.Outlet = this._repository.GetOutletById(outletId); 

     return this; 
    } 

    public OutletViewModelBuilder WithCountryList() 
    { 
     this._viewModel.CountryList = this._repository.GetCountryList(); 

     return this; 
    } 
} 

最後,IOutletViewModelBuilder接口

public interface IOutletViewModelBuilder 
{ 
    OutletViewModel Build(); 

    OutletViewModelBuilder WithOutlet(int outletId); 

    OutletViewModelBuilder WithCountryList(); 
} 
+0

如果這個問題不明確。我如何Moq的OutletViewModelBuilder對象?我應該改變嘲笑框架嗎? – Yag

+0

你可以發佈你想模擬的'IOutletViewModelBuilder'的代碼嗎? – froeschli

回答

5

它看起來像的主要問題是,你的WithOutlet和WithCountryList方法返回一個具體OutletViewModelBuilder,而不是返回一個IOutletViewModelBuilder。我認爲你需要像這樣:

public interface IOutletViewModelBuilder 
{ 
    OutletViewModel Build(); 
    IOutletViewModelBuilder WithOutlet(int outletId); 
    IOutletViewModelBuilder WithCountryList(); 
} 

那麼你的嘲弄:

var myViewModel = TheOutletViewModelForTesting(); 
var mockBuilder = new Mock<IOutletViewModelBuilder>(); 

mockBuilder.Setup(m => m.WithOutlet(It.IsAny<int>())).Returns(mockBuilder.Object); 
mockBuilder.Setup(m => m.WithCountryList()).Returns(mockBuilder.Object); 
mockBuilder.Setup(m => m.Build()).Returns(myViewModel); 

// rest of your test that validates that myViewModel is passed correctly to your view 
+0

就是這樣!感謝Brian,這幾乎令人尷尬。非常感謝!所以原來問題就是我。 :-) – Yag