为什么会抛出异常

时间:2013-04-11 15:29:39

标签: c# rhino-mocks

测试:

[TestMethod]
public void TestStringWithValidAndInvalid()
{
    MockRepository mocks = new MockRepository();
    ICentipedeCore mockCore = mocks.DynamicMock<ICentipedeCore>();
    IPythonEngine pythonEngine = mocks.StrictMock<IPythonEngine>();
    IPythonByteCode mockPythonByteCode = mocks.Stub<IPythonByteCode>();

    mockCore.Stub(c => c.PythonEngine)
            .Return(pythonEngine);

    pythonEngine.Expect(e => e.Compile(Arg<String>.Is.Equal("\"String\""),
                                       Arg<PythonByteCode.SourceCodeType>.Is.Anything))
                .Return(mockPythonByteCode);

    pythonEngine.Expect(e => e.Evaluate(Arg<IPythonByteCode>.Is.Equal(mockPythonByteCode),
                                        Arg<PythonScope>.Is.Anything))
                .Return(3);

    pythonEngine.Expect(e => e.Compile(Arg<String>.Is.Equal("this is invalid python"),
                                       Arg<PythonByteCode.SourceCodeType>.Is.Anything))
                .Throw(new PythonParseException(mocks.Stub<Exception>()));


    ActionWrapper testAction = new ActionWrapper(mockCore);

    var original = @"{1+2} with {invalid python}";
    var expected = "3 with {invalid python}";
    var result = testAction.ParseStringForVariable(original); // ActionTest.cs: line 267

    mocks.VerifyAll();
    Assert.AreEqual(expected, result);
}

测试中的方法(由包装器公开):

protected String ParseStringForVariable([NotNull] String str)
{
    IPythonEngine pythonEngine = GetCurrentCore().PythonEngine;

    for (int i = 0; i < str.Length; i++)
    {
        if (str[i] != '{')
        {
            continue;
        }

        int opening = i;
        foreach (var expression in from closing in str.IndexesWhere('}'.Equals)
                                   where closing > opening
                                   select new
                                          {
                                              Template = str.Substring(opening, closing - opening + 1),
                                              Code = str.Substring(opening + 1, closing - opening - 1)
                                          })
        {
            IPythonByteCode compiled;
            try
            {
                compiled = pythonEngine.Compile(expression.Code, PythonByteCode.SourceCodeType.Expression);
            }
            catch (PythonParseException)
            {
                // not valid python, try next expression
                continue;
            }
            dynamic r = pythonEngine.Evaluate(compiled);
            String result = r.ToString(); //  Action.cs: line 217, wrapped at  ActionTest.cs: line 96
            str = str.Replace(expression.Template, result);
            break;
        }
    }

    return str;
}

例外:

  

Microsoft.CSharp.RuntimeBinder.RuntimeBinderException:无法对空引用执行运行时绑定

dynamic r = pythonEngine.Evaluate(compiled); r为空后,该行会抛出异常。但我不知道为什么 - compiled与mockPythonByteCode具有相同的值,pythonEngine是在测试中创建的模拟,而相同的调用在不同的方法中工作。这里唯一的区别是pythonEngine.Compile在不同的输入上有两个期望,结果不同。

问题是,我有TestStringWithValidCode()TestStringWithInvalidCode(),两者都运行良好,我合并为TestStringWithValidAndInvalid(),所以每一半应该工作

1 个答案:

答案 0 :(得分:1)

检查null会更加谨慎,因为由于代码的结构,当catch发生且compiled为空时它会运行碰巧发生的代码期望compiled不会为空。

所以

变化:

       catch (PythonParseException)
        {
            // not valid python, try next expression
            continue;
        }
        dynamic r = pythonEngine.Evaluate(compiled);

       catch (PythonParseException)
        {
            // not valid python, try next expression
            continue;
        }
       if (compiled != null)
       {
        dynamic r = pythonEngine.Evaluate(compiled);
        String result = r.ToString(); //  Action.cs: line 217, wrapped at  ActionTest.cs: line 96
        str = str.Replace(expression.Template, result);
       }
       else
       {
           str="Exception Caught";
       }
       break;