2012-07-19 145 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

相关问题