使用NInject为WebApi控制器提供Rhino Mock对象 - Stubs总是返回null

时间:2017-03-10 17:34:06

标签: asp.net-web-api ninject owin rhino-mocks

我正在尝试使用Owin内存服务器对我的WebApi控制器进行单元测试,该服务器是从我的 [ClassInitialize] (MS Test)方法调用的。我需要通过DI容器将我的存储库对象 IFourSquareRepository 的模拟实例注入我的控制器。当测试类[ClassInitialize]方法执行时,Owin服务器设置,静态Ninject IKernel实例及其绑定在WebApi项目的Owin配置类中处理:

            kernel.Bind<IFourSquareRepository>().ToMethod( 
            context => 
                {
                    return MockRepository.GenerateMock<IFourSquareRepository>(); 
                    // This block runs only once ...
                    // But stubs from the test method return null when the test call 
                    // fires up the controller ...
                }
                ).InSingletonScope();

从我的测试项目中的测试方法中进行评估时,这些存根可以预测地工作(即:它们返回我在下面的存根定义中指定的值)。

我的 [TestMethod] 案例为我的控制器所依赖的模拟接口(IFourSquareRepository)的方法创建存根,并调用解析到我的WebApi上的WebApi端点控制器如下所示 - (因为我发送了一个HttpClient请求,我不能手动将我的模拟对象注入控制器实例 - 我依靠WebApi管道来创建控制器实例,所以我必须使用一个DI容器来注入模拟的 IFourSquareRepository 对象进入控制器):

       [TestMethod]
    public void Test1_InMemServer()
    {
        var testRet = new BookmarkedPlace() { Id = 99 };
        string userName = "Joe";
        this.MockRepository.Stub(
            repo => repo.GetFirstBookmarkedPlace()).Return(testRet);
        // stub for test Repo IF method

        // Act User the base class static HttpClient to talk to the Owin-hosted WebApi  
        var response = InMemoryTest.HttpClient.GetAsync( string.Format("/api/places/{0}", userName) ).Result;
        var body = response.Content.ReadAsStringAsync().Result;

        // Assert
        Assert.IsTrue(response.IsSuccessStatusCode, "Request Failed ");


    }

我的问题是无论我做什么,当控制器(从我上面的HttpClient请求调用)调用stubbed方法时,它ALLWAYS返回NULL !!

       public IEnumerable<BookmarkedPlace> Get(string userName, int page = 0, int pageSize = 10)
    {
        IQueryable<BookmarkedPlace> query;

        query = this.Repository.GetFirstBookmarkedPlace();
        // Mock Repo call returning null !

        // Other stuff goes here ...

        return results;

    }

我已经在这个问题上敲了几天 - 有什么想法吗?

1 个答案:

答案 0 :(得分:0)

我认为原因是当你创建你的模拟存储库时,我确信它后端必须使用某种上下文作为调用的依赖项也会被存根,所以不会映射到实际的dbsets。

在过去,我使用以下方式模拟我的存储库并在我的Base Test类中获取DbSet的实例(因为这对于生成是常见的)

public static IDbSet<T> GenerateSet<T>(IList<T> data) where T : class
    {
        IQueryable<T> queryable = data.AsQueryable();
        IDbSet<T> dbSet = MockRepository.GenerateMock<IDbSet<T>, IQueryable>();
        dbSet.Stub(x => x.Provider).Return(queryable.Provider);
        dbSet.Stub(x => x.Expression).Return(queryable.Expression);
        dbSet.Stub(x => x.ElementType).Return(queryable.ElementType);
        dbSet.Stub(x => x.GetEnumerator()).Return(null).WhenCalled(x => queryable.GetEnumerator());

        return dbSet;
    }

然后在Initialise中的Test类中执行:

[TestInitialize]
    public new void Initialize()
    {
        base.Initialize();
        _context = MockRepository.GenerateMock<YourContextInterface>();
        _context.Stub(x => x.YourDbSet).PropertyBehavior();
        _context.YourDbSet= GenerateSet(YourDbSet);
    }