2011-06-19 45 views
1

来自我一天的第二个MSpec问题,这是一个新的记录。我试图非常快速地理解MSpec,并且遇到了MSpec一直存在的一些旧问题。针对存储库进行单元测试,使用MSpec,我正在做对吗?

场景:我有一个存储库,其中包含一堆漫画。现在我只需要在一个名称参数中过滤这个参数,这是一个字符串。据我所知,稍后我需要在更多属性上过滤这个属性,我决定创建一个类,它通过IoC接受我的ICartoonRepository,并包含一个名为GetByName(string name)的简单方法。

你可能会认为这是矫枉过正,但我​​试图教自己如何使用MSpec并以更多TDD方式工作。

所以我创建如下:

[Subject(typeof(CartoonViewModelBuilder))] 
public class when_cartoon_repository_is_asked_to_get_by_id : specification_for_cartoon_viewmodel_builder 
{ 
    static string name; 
    static Cartoon the_cartoon; 
    static Cartoon result; 

    Establish context =() => 
    { 
     name = "Taz"; 
     the_cartoon = new Cartoon(); 
     the_cartoon_repository.Stub(r => r.GetAll().Where(x=>x.Name == name).FirstOrDefault()).Return(the_cartoon); 
    }; 

    Because of =() => result = subject.GetByName(name); 

    It should_return_cartoon =() => result.ShouldBeTheSameAs(the_cartoon); 
} 

这失败的存根作为仓库是空的。我有一些其他测试通过很好(简单地测试GetAll()等)。我是否需要将内容添加到存储库以进行测试?这是我难倒的地方,请温柔。另外,如果我在存根中编写linq语句,看起来好像我在实际执行和测试中做了两次。这是关键吗?它没有感觉没错。有更好的方法可以写这个测试吗?

为了清楚起见,这里是实际执行(我省略了接口和类,它只是有一个属性:

public class CartoonViewModelBuilder: ICartoonViewModelBuilder 
{ 
    readonly ICartoonRepository _cartoonRepository; 

    public CartoonQueryObject(ICartoonRepository cartoonRepository) 
    { 
     _cartoonRepository = cartoonRepository; 
    } 

    public IList<Cartoon> GetAllCartoons() 
    { 
     return _cartoonRepository.GetAll(); 
    } 

    public Cartoon GetByName(string name) 
    { 
     return _cartoonRepository.GetAll().Where(x => x.Name == name).FirstOrDefault(); 
    } 
} 

编辑1:基于缺乏反应,我应该说如果我使用的是像NUnit这样的东西,我会在测试类上创建一个类似于“LoadDummyData”的方法,并将数据投入到存储库中,然后执行复杂的过滤或查看模型构建以及手动检查发生了,这使得大的重构成为一件苦差事,看起来好像规格允许你避免这种情况吗?

编辑2:这是我的更正现在通过的测试。让我知道如果我做对了,我想我是。再次感谢握手!

static string name; 
    static Cartoon the_cartoon; 
    static Cartoon result; 
    static IQueryable<Cartoon> the_cartoons; 

    Establish context =() => 
    { 
     name = "Taz"; 
     the_cartoon = new Cartoon {Name = name}; 
     the_cartoons = new List<Cartoon> {the_cartoon, new Cartoon(), new Cartoon() }.AsQueryable(); 
     the_cartoon_repository.Stub(r => r.GetAll()).Return(the_cartoons.ToList()); 
    }; 

    Because of =() => result = subject.GetByName(name); 

    It should_return_cartoon =() => result.ShouldBeTheSameAs(the_cartoon); 

编辑3:给你两个分,但是我只能不幸地给一个最好的答案。

+0

什么类型是主题?并且为什么您将知识库存档,因为这是您的系统正在测试中? –

+0

是的,你的代码现在看起来在技术上还行。我在回答中添加了评论。 – NOtherDev

回答

1

此测试失败的实际原因是您嘲笑您的存储库的方式。如果像r.GetAll().Where(x=>x.Name == name).FirstOrDefault()这样的方法链很容易被嘲笑,我会非常惊讶,因为它使用LINQ扩展方法和lambda子句。该框架应该真的抛出NotSupported异常或让你知道你不能模拟LINQ查询作为一个整体。

嘲笑LINQ查询结果,你应该提供适当的准备基础数据的收集,这是LINQ查询的起点。在你的例子中,你应该嘲笑r.GetAll()返回一个包含你的元素的专有名称的集合。实际的查询将在您的“模拟”数据上运行并检索您期望的对象。

这样就省去了重复的LINQ查询代码和测试,有什么奇怪的,因为你注意到。

编辑:编辑中的代码就像我建议的一样,技术上没问题。

无论如何,到目前为止,如你所说,这有点矫枉过正。除了调用模拟存储库之外,被测试的类不会执行任何操作,因此该测试的值很小。但如果你想在GetByName方法中有更多的逻辑,这可能是一个好的开始。

1

如果你想测试你的版本库的实现,不要把它存根! MSpec与否,我会将已知项目的列表添加到存储库,然后使用GetByName发出查询。然后断言只是你期望的物品被退回。我也将使用ShouldEqual作为存储库可能与您添加的项目一起工作,并返回一个不同的实例,尽管被认为是相等的(聚合ID是相等的)。

相关问题