2012-07-19 144 views
3

我寫道,通過連接數據一起創建一個新對象以下LINQ查詢,你可以看到:如何在模擬數據庫上下文時使用DefaultIfEmpty?

var translations = from t in context.Translations 
          join token in context.Tokens on t.Guid equals token.Guid 
          join t2 in context.Translations on new { t.Guid, LanguageCode = "fr" } equals new { t2.Guid, t2.LanguageCode} into j //TODO: fr needs to be replaced by the language of the translators account 
          from j2 in j.DefaultIfEmpty() 
          where t.LanguageCode == String.Empty 
          orderby t.Text 
          select new TranslationView 
            { 
             Guid = t.Guid, 
             LanguageCode = j2.LanguageCode, 
             SourceText = t.Text, 
             Translation = j2.Text, 
             IsNew = j2.Text == null, 
             Notes = token.Notes, 
             Required = token.Required, 
             Type = (Token.TokenType)token.Type, 
             Location = (Token.LocationType)token.Location 
            }; 

的問題是,我現在想寫與Rhino.Mocks一個單元測試,它返回錯誤Object reference not set to an instance of an object.

所以我現在的問題是,有沒有更好的方式,這個查詢可以寫?一種既能在真實情況下也能在單元測試情況下工作的方式?

我試着在DefaultIfEmpty()位傳遞一個值,它使它適用於模擬,但主代碼失敗。

編輯 單元測試代碼:

[Test] 
    public void Build_Translation_List_TwoItems_Context() 
    { 
     //Arrange: Setup context 
     var context = setupContext(); 

     //Act: Pass the context through 
     var result = TranslationHelpers.BuildTranslationList(context, 1); 

     //Result 
     result.TranslationList.Count.ShouldEqual(2); 
     result.PagingInfo.TotalItems.ShouldEqual(2); 
    } 

SetupContext方法:

public static ITranslationContext setupContext() 
    { 
     var context = new Mock<ITranslationContext>(); 
     context.SetupProperty(x => x.Tokens, new UnitTestHelpers.FakeDbSet<Token> 
               { 
                new Token 
                 { 
                  DateAdded = DateTime.Now, 
                  Guid = Guid.Parse("f3099a43-e12d-4ea3-ba06-265fde807f03"), 
                  LastUpdated = DateTime.Now, 
                  Location = (short)0, 
                  Type = (short)0, 
                  LocationDescription = "Test 1", 
                  Notes = "Testing 1", 
                  Required = "Testing" 
                 }, 

                new Token 
                 { 
                  DateAdded = DateTime.Now, 
                  Guid = Guid.Parse("7D6937D8-F7E1-4B92-934E-465683874B65"), 
                  LastUpdated = DateTime.Now, 
                  Location = (short)0, 
                  Type = (short)0, 
                  LocationDescription = "Test 3", 
                  Notes = "Testing 3", 
                  Required = "Testing" 
                 }, 

               }); 
     context.SetupProperty(x => x.Translations, new UnitTestHelpers.FakeDbSet<Translation> 
                { 
                 new Translation{Guid = Guid.Parse("f3099a43-e12d-4ea3-ba06-265fde807f03"), LanguageCode = String.Empty, Text = "Testing 1"}, 
                 new Translation{Guid = Guid.Parse("f3099a43-e12d-4ea3-ba06-265fde807f03"), LanguageCode = "fr", Text = ""}, 
                 new Translation{Guid = Guid.Parse("7D6937D8-F7E1-4B92-934E-465683874B65"), LanguageCode = String.Empty, Text = "Testing 3"}, 
                 new Translation{Guid = Guid.Parse("7D6937D8-F7E1-4B92-934E-465683874B67"), LanguageCode = "fr", Text = "Testing 4"} 

                }); 
     return context.Object; 
    } 

任何幫助將非常感激。

回答

3

DefaultIfEmpty()不會創建一個 「默認」 J2。即使j2爲空,它也會得到數據。

這就像一個SQL LEFT JOIN

所以你要測試無效,以避免NRE。

代替

LanguageCode = j2.LanguageCode 

嘗試做

LanguageCode =j2 != null ? j2.LanguageCode : string.Empty // or null 
+0

是的,它應該像一個左連接。它從主數據庫工作正常,只有當我運行一個模擬,它似乎是一個問題。 – 2012-07-19 12:03:30

+0

@GazWinter你是否試圖刪除你的查詢的選擇部分,看看NRE是否真的從那裏來? – 2012-07-19 12:10:41

+0

不,我不會,我會給它一個去,讓你知道發生了什麼。 – 2012-07-19 12:13:01

0

將模擬的上下文傳遞給你的方法,LINQ將完成它的工作。然後驗證TranslationView對象的返回列表。

這是您的測試應該如何看起來像:

List<Translations> translations = // create translations 
List<Tokens> tokens = // create tokens 
var context = MockRepository.GenerateStub<IMyContext>();    
context.Stub(c => c.Translations).Return(translations); 
context.Stub(c => c.Tokens).Return(tokens); 

var foo = new Foo(context); 
var views = foo.GetTranslationView(); 
// verify returned views 
+0

我沒有通過嘲笑上下文。 – 2012-07-19 11:41:22

+0

@GazWinter所以,你在哪裏得到一個錯誤? – 2012-07-19 11:44:57

+1

linq不會從上下文返回事物。它與DefaultifEmpty有關。在活動數據庫中,如果存在空值,那麼它只是創建一個新的實例,但是當您嘗試使用模擬上下文時,它不會像空值那樣。 – 2012-07-19 11:52:52

相關問題