Moq设置在被告知时不返回值

时间:2015-07-10 18:43:13

标签: c# unit-testing moq

我的测试场景中有这个:

    @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    mNavigationDrawerFragment = (NavigationDrawerFragment)
            getSupportFragmentManager().findFragmentById(R.id.navigation_drawer);
    mTitle = getTitle();

    // Set up the drawer.
    mNavigationDrawerFragment.setUp(
            R.id.navigation_drawer,
            (DrawerLayout) findViewById(R.id.drawer_layout));

    SupportMapFragment mapFragment = SupportMapFragment.newInstance(new GoogleMapOptions().compassEnabled(true).zoomControlsEnabled(true).mapToolbarEnabled(true));
    FragmentManager fragmentManager = getSupportFragmentManager();

    // call getMapAsync() to set OnMapReadyCallback on map fragment
    mapFragment.getMapAsync(this);

    fragmentManager.beginTransaction().add(R.id.container, mapFragment, "map").commit();

    mTitle = "Some Title";
    restoreActionBar();
}

查看Get方法时:

var dbConnection = new Mock<IDbConnection>();
dbConnection.Setup(x => x.SearchFor<User>("users", y => y.Password =="12345" 
   && y.Username == "tester")).Returns(new List<User>{
       new User{
          Username = "tester",
           Password = "12345"
       }}.AsQueryable());

var users = new Users.Users(dbConnection.Object);
var user = users.Get("tester", "12345");

它应该根据我在互联网上找到的大多数样本工作,但它总是给我:

public User Get(string username, string password){
    var total = _dbConnection.SearchFor<User>("users", y => 
        y.Password == password && 
        y.Username == username).Single();
    return total;
}

当我将Get方法更改为:

System.InvalidOperationException: Sequence contains no elements

它神奇可行,但get方法在业务层,就像我们都知道的那样......设置硬编码的用户名和密码永远不会好。

问题是:如何正确设置moq?我做错了什么?

1 个答案:

答案 0 :(得分:1)

因此您需要进行设置,期望参数"users"y => y.Password == "12345" && y.UserName == "tester"。但是,你的第二个参数是lambda,很难比较(如果不是不可能的话?)。所以,当Moq检查你是否已经打电话时,它最终会试图比较lambdas,这可能会失败。

例如,下面的代码显示了两个看似相同的函数,但它们并不相同:

Func<bool> a = () => true;
Func<bool> b = () => true;
(a == b).Dump(); //False
a.Equals(b).Dump(); //False

因此,Moq不知道使用您设置的返回值。

您可能需要实现一个实际运行lambda的模拟存储库,而不是尝试查找您提供的那个。

这样的事情:

class TestRepo
{
    public void Add<T>(T myType)
    {
        //add to an in-memory "database"
    }
    public IEnumerable<T> Get<T>(Expression<Func<T, bool>> filter)
    {
        return inMemoryDataBase.Where(filter);
    }
}

这将使您的Get方法看起来像这样:

public User Get(string username, string password){
    var total = RealRepo.Get<User>(y => 
        y.Password == "12345" && 
        y.Username == "tester").Single();
    return total;
}

你的考试:

var repo = new TestRepo();
repo.Add(new User { Username = "tester", Password = "12345" });
var users = new Users.Users(dbConnection.Object);
var user = users.Get("tester", "12345");

这是一个有点相关的问题,用户试图找到一种方法来唯一地识别一个lambda,以便它们可以被比较&#34;以你希望的方式。我不知道那里找到了任何完美的解决方案。 Link