如何在Autofac中为InstancePerRequest服务编写单元测试(或回归测试)

时间:2017-04-27 19:07:21

标签: c# unit-testing dependency-injection autofac

过去,我曾参与过许多Autofac组件的复杂项目。为了检查一切是否可以解决,我们编写了一个单元测试,试图解决所有必要的(顶级)组件。

但是现在我正试图在ASP.NET MVC项目中第一次这样做。

我注册了这样的ApiControllers:

var containerBuilder = new ContainerBuilder();
foreach (var module in ModuleRepository.GetModulesForWebsite())
{
    containerBuilder.RegisterModule(module);
}

var container = containerBuilder.Build();

foreach (var componentRegistryRegistration in container.ComponentRegistry.Registrations)
{
    foreach (var service in componentRegistryRegistration.Services.OfType<TypedService>())
    {
        if (service.ServiceType.IsAssignableTo<ApiController>())
        {
            var implementation = container.Resolve(service.ServiceType);
            implementation.Should().NotBeNull();
        }
    }
}

我想要像这样测试:

Autofac.Core.DependencyResolutionException: Unable to resolve 
the type 'Website.APIControllers.Clean.IngredientsController' 
because the lifetime scope it belongs in can't be located. The 
following services are exposed by this registration:
- MyProject.MyController

然而,这导致了这个例外:

import java.io.IOException;
import java.net.BindException;
import java.net.InetAddress;
import org.ice4j.Transport;
import org.ice4j.TransportAddress;
import org.ice4j.ice.Agent;
import org.ice4j.ice.IceMediaStream;
import org.ice4j.ice.harvest.StunCandidateHarvester;

public class IceTest {

public static void main(String[] args) throws Exception {
    Agent agent = new Agent(); // A simple ICE Agent

    /*** Setup the STUN servers: ***/
    String[] hostnames = new String[] { "jitsi.org", "numb.viagenie.ca", "stun.ekiga.net" };
    // Look online for actively working public STUN Servers. You can find
    // free servers.
    // Now add these URLS as Stun Servers with standard 3478 port for STUN
    // servrs.
    for (String hostname : hostnames) {
        try {
            // InetAddress qualifies a url to an IP Address, if you have an
            // error here, make sure the url is reachable and correct
            TransportAddress ta = new TransportAddress(InetAddress.getByName(hostname), 3478, Transport.UDP);
            // Currently Ice4J only supports UDP and will throw an Error
            // otherwise
            agent.addCandidateHarvester(new StunCandidateHarvester(ta));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /*
     * Now you have your Agent setup. The agent will now be able to know its
     * IP Address and Port once you attempt to connect. You do need to setup
     * Streams on the Agent to open a flow of information on a specific
     * port.
     */

    IceMediaStream stream = agent.createMediaStream("audio");
    int port = 5000; // Choose any port
    try {
        agent.createComponent(stream, Transport.UDP, port, port, port + 100);
        // The three last arguments are: preferredPort, minPort, maxPort
    } catch (BindException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IllegalArgumentException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    /*
     * Now we have our port and we have our stream to allow for information
     * to flow. The issue is that once we have all the information we need
     * each computer to get the remote computer's information. Of course how
     * do you get that information if you can't connect? There might be a
     * few ways, but the easiest with just ICE4J is to POST the information
     * to your public sever and retrieve the information. I even use a
     * simple PHP server I wrote to store and spit out information.
     */
    String toSend = null;
    try {
        toSend = SdpUtils.createSDPDescription(agent);
        // Each computersends this information
        // This information describes all the possible IP addresses and
        // ports
    } catch (Throwable e) {
        e.printStackTrace();
    }

    /*The String "toSend" should be sent to a server. You need to write a PHP, Java or any server. 
     * It should be able to have this String posted to a database. 
     * Each program checks to see if another program is requesting a call. 
     * If it is, they can both post this "toSend" information and then read eachother's "toSend" SDP string. 
     * After you get this information about the remote computer do the following for ice4j to build the connection:*/

    String remoteReceived = ""; // This information was grabbed from the server, and shouldn't be empty.
    SdpUtils.parseSDP(agent, remoteReceived); // This will add the remote information to the agent.
    //Hopefully now your Agent is totally setup. Now we need to start the connections:

    agent.addStateChangeListener(new StateListener()); // We will define this class soon
    // You need to listen for state change so that once connected you can then use the socket.
    agent.startConnectivityEstablishment(); // This will do all the work for you to connect
}

任何人都知道如何才能优雅地解决这个问题?我应该伪造一个HttpRequest吗?我该怎么做?或者还有其他选择吗?

1 个答案:

答案 0 :(得分:2)

There are docs here on how to test per request dependencies.

根据问题中的评论主题,听起来你将每个请求依赖项切换到每个生命周期范围(这就是ASP.NET Core现在处理的事情)。

对于问题的未来读者,实际上有一些选项,因此请查看文档以获取更多信息。