2013-04-11 106 views
1

測試:爲什麼這拋出異常

[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(),所以每半應該工作。

+3

我們是否意味着猜出這些例外正在拋出? – spender 2013-04-11 15:32:17

+1

在拋出異常的什麼時候?您可以在測試開始時設置一個斷點,而不是選擇「運行測試」,而是選擇「調試測試」來讓您逐步完成代碼。這可能也會給你你的答案,因爲你會看到空引用。 – IWriteApps 2013-04-11 15:33:03

+0

該死的,知道我錯過了什麼。我知道null引用是在哪裏('r'在'string result = r.ToString();'中爲null,(註釋爲217行),但我看不到null從哪裏來。 – RoadieRich 2013-04-11 20:46:02

回答

1

一種空的檢查會比較謹慎,因爲由於代碼的結構,當catch發生和compiled爲null,並且它然後運行代碼恰好預計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; 
相關問題