2009-07-13 33 views
5

我试图用VS 2008的内置单元测试框架和我正在测试的方法调用Environment.Exit(0)来编写C#单元测试。当我在单元测试中调用此方法时,我的单元测试被中止。该方法确实应该调用Exit,我想要一种方法来测试它的功能,并且测试它使用的退出代码。我该怎么做?我看着Microsoft.VisualStudio.TestTools.UnitTesting Namespace,但没有看到任何看起来相关的东西。VS2008单元测试 - 断言方法退出

[TestMethod] 
[DeploymentItem("myprog.exe")] 
public void MyProgTest() 
{ 
    // Want to ensure this Exit's with code 0: 
    MyProg_Accessor.myMethod(); 
} 

同时,这里就是我想测试代码的要点:

static void myMethod() 
{ 
    Environment.Exit(0); 
} 

编辑:这里是我在我的测试方法中使用的解决方案,这要归功于RichardOD

Process proc; 

try 
{ 
    proc = Process.Start(path, myArgs); 
} 
catch (System.ComponentModel.Win32Exception ex) 
{ 
    proc = null; 
    Assert.Fail(ex.Message); 
} 

Assert.IsNotNull(proc); 
proc.WaitForExit(10000); 
Assert.IsTrue(proc.HasExited); 
Assert.AreEqual(code, proc.ExitCode); 

回答

4

这听起来像一个令人难以置信的糟糕主意。 Environment.Exit(0)显然会按照规定执行,因此你的单元测试正在破裂。

如果你真的想要测试这个,你可以启动一个单独的程序并检查返回代码 - 看看它在Process.Start中包装它。

我想另一个选择是将这个代码分解出来并注入一个test spy,或者使用一个模拟对象来验证正确的行为。

也许你可以用Typemock Isolator做些什么 - 我相信这可以让你mock static methods

+0

+1 TypeMock隔离在这里 - 这是我知道它可以让你拦截和嘲笑绝对什么的唯一解决方案。 – 2009-07-13 20:07:52

+0

能够嘲讽静态方法的危险在于,你不会像使用它们那样容易地使用它们。实际上,我发现(对于我的代码)被迫花费更多的精力来使静态方法成为一件好事,因为除非它们是绝对最佳解决方案,否则我不会使用它们。这有助于使用更好的技术强制开发IMO。不利的一面是,当他们确实有意义时(或者没有考虑测试构建框架),当你与这些静态方法进行交互时,你就不得不跳出箍臼。 – tvanfosson 2009-07-13 20:15:22

3

你将无法测试这个 - Environment.Exit完全杀死应用程序。这意味着任何使用此代码的AppDomain都将完全卸载,无论它是您的生产应用程序还是单元测试框架。

2

这里你唯一的选择是用fakie Exit方法模拟Environment类。

5

您需要为Environment类创建一个包装器,然后在代码中使用包装器。对于你的单元测试,注入一个模拟版本的包装。以下示例使用RhinoMocks验证该方法是否使用期望的参数调用包装器。

public class EnvironmentWrapper 
{ 
    public virtual void Exit(int code) 
    { 
     Environment.Exit(code); 
    } 
} 


public class MyClass 
{ 
    private EnvironmentWrapper Environment { get; set; } 

    public MyClass() : this(null) { } 

    public MyClass(EnvironmentWrapper wrapper) 
    { 
     this.Environment = wrapper ?? new EnvironmentWrapper(); 
    } 

    public void MyMethod(int code) 
    { 
     this.Environment.Exit(code) 
    } 
} 


[TestMethod] 
public void MyMethodTest() 
{ 
    var mockWrapper = MockRepository.GenerateMock<EnvironmentWrapper>(); 

    int expectedCode = 5; 

    mockWrapper.Expect(m => m.Exit(expectedCode)); 

    var myClass = new MyClass(mockWrapper); 

    myclass.MyMethod(expectedCode); 

    mockWrapper.VerifyAllExpectations() 
} 
0

您可以为方法添加一个参数,以将它传递给一个假的环境,其中exit()方法不会退出。

你可以从你的应用程序调用的方法中提取这个参数化方法,然后单元测试提取的函数。这样,你不必修改你的应用程序。

0

是在我脑海中的唯一事情是沿东西:

static void myMethod() 
{ 
    DoEnvironmentExit(0); 
} 

static void DoEnvironentExit(int code) 
{ 
    #if defined TEST_SOLUTION 
     SomeMockingFunction(code); 
    #else 
     Environment.Exit(code); 
    #endif 
}