【问题标题】:How to mock dependencies for a WebApi 2 controller when using MEF 2 (System.Composition)?使用 MEF 2 (System.Composition) 时如何模拟 WebApi 2 控制器的依赖项?
【发布时间】:2014-10-29 10:53:00
【问题描述】:

使用 MEF (System.ComponentModel.Composition) 可以将模拟对象添加到容器中。

container.ComposeExportedValue(mock.Object);

参考:How to use Moq to satisfy a MEF import dependency for unit testing?

如何使用便携式 MEF 库 (System.Composition) 实现这一点?

关于更多上下文,我将发布我目前掌握的一些代码。

我正在内存中的 ASP.NET Web API 上创建 xBehave.net 集成测试。

我是这样设置客户端的。

config = new HttpConfiguration();
WebApiConfig.Register(config);
config.DependencyResolver = MefConfig();
server = new HttpServer(config);
Client = new HttpClient(server);
Request = new HttpRequestMessage();

我将我的 MEF 配置设置为 WebApiContrib.IoC.Mef 的默认配置。

private static IDependencyResolver MefConfig()
{
    var conventions = new ConventionBuilder();
    conventions.ForTypesDerivedFrom<IHttpController>().Export();
    conventions.ForTypesMatching(
        t => t.Namespace != null && t.Namespace.EndsWith(".Parts"))
        .Export()
        .ExportInterfaces();

    var container = new ContainerConfiguration()
        .WithAssemblies(
            new[] { Assembly.GetAssembly(typeof(ICache)) }, conventions)
        .CreateContainer();

    return new MefDependencyResolver(container);
}

这是我要测试的控制器的签名。它从缓存中读取。

public MyController(ICache cache) { }

这是测试。模拟是使用Moq 创建的。

[Scenario]
public void RetrieveOnPollingRequest()
{
    const string Tag = "\"tag\"";
    string serverETag = ETag.Create(Tag);

    "Given an If-None-Match header"
        .f(() => Request.Headers.IfNoneMatch.Add(
            new EntityTagHeaderValue(Tag)));
    "And the job has not yet completed"
        .f(() =>
            {
                string tag = serverETag;
                this.MockCache.Setup(x => x.StringGet(tag)).Returns(Tag);
            });
    "When retrieving jobs"
        .f(() =>
            {
                Request.RequestUri = uri;
                Response = Client.SendAsync(Request).Result;
            });
    "Then the status is Not-Modified"
        .f(() =>
            Response.StatusCode.ShouldEqual(HttpStatusCode.NotModified));
}

那么我如何将那个模拟放入容器而不是已经导出的部分?还是我不?我需要去使用不同的 IoC 容器吗?

【问题讨论】:

    标签: c# asp.net-web-api mef bdd ioc-container


    【解决方案1】:

    您可以使用来自 MEF CodePlex 站点的 Microsoft.Composition.Demos.ExtendedPartTypes 示例中采用的方法来执行此操作。下面显示了为IAmMocked 服务注册实例mockObject

    var container = new ContainerConfiguration()
        .WithExport<IAmMocked>(mockObject)
        .WithAssemblies(
            new[] { Assembly.GetAssembly(typeof(ICache)) }, conventions)
        .CreateContainer();
    

    你可以在这里找到完整的代码:http://mef.codeplex.com/SourceControl/latest#oob/demo/Microsoft.Composition.Demos.ExtendedPartTypes/Program.cs

    我们打算在某个时候把它“装进盒子里”,但我不相信它已经发生了。如果您在运行它时遇到任何问题,请告诉我!

    【讨论】:

    • 这很好,谢谢。我可以为一个测试套件设置一个带有导出模拟的测试容器,然后根据测试用例修改模拟对象。
    猜你喜欢
    • 1970-01-01
    • 2015-01-16
    • 2011-06-15
    • 1970-01-01
    • 2011-06-25
    • 2015-10-21
    • 2015-03-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多