0

I'm trying to unit test the following function with pytest.

@login_sys.route("/users/register", methods=["POST"])
def register():
    users = mongo.db.users # TRYING TO PATCH THIS
    print("--->{}".format(type(users)))
    email = request.get_json()["email"]
    response = users.find_one({"email": email})
    if response:
        result = jsonify({"result": "email already registered"})
        return result

    first_name = request.get_json()["first_name"]
    last_name = request.get_json()["last_name"]

    password = bcrypt.generate_password_hash(request.get_json()["password"]).decode(
        "utf-8"
    )
    created = datetime.utcnow()

    user_id = users.insert(
        {
            "first_name": first_name,
            "last_name": last_name,
            "email": email,
            "password": password,
            "created": created,
        }
    )

    new_user = users.find_one({"_id": user_id})

    result = {"email": new_user["email"] + " registered"}

    return jsonify({"result": result})

Following is the test I wrote

@pytest.fixture(scope="module")
def client():
    app.config['TESTING'] = True
    app.register_blueprint(login_sys)
    with app.test_client() as client:
        return client

def test_register(client, monkeypatch):
    print(type(client))
    mimetype = 'application/json'
    headers = {
        'Content-Type': mimetype,
        'Accept': mimetype
    }
    userInfo = {
            "first_name": "admin",
            "last_name": "admin",
            "email": "admin@gmail.com",
            "password": "admin",
        }
    def mock_db():
        return mongomock.MongoClient().db.collection
    print(type(mongomock.MongoClient().db.collection)) 
    #class'mongomock.collection.Collection'>
    monkeypatch.setattr(mongo.db, 'users', mock_db)
    rv = client.post("/users/register", data=json.dumps(userInfo), headers=headers)
    dprint(rv.data)
    assert True

I'm trying to replace the mongo.db.users with the fake one I made with mongomock mongomock.MongoClient().db.collection. However, when I ran this test, it shows an attribute error shown below:

E AttributeError: 'function' object has no attribute 'find_one'

I'm not sure why the mock_db() returns a type function instead of type <class'mongomock.collection.Collection'>

let me know if anyone has any suggestions.

Thank you.

BOB
  • 151
  • 3
  • 13
  • Is your patching code expecting `users` to be a fixed or dynamic attribute of `db`? – D. SM Jun 27 '20 at 02:31
  • I want to be able to add more data to the fake collection, so I guess it's dynamic. @D.SM – BOB Jun 27 '20 at 02:47
  • @D.SM let me know if you have another suggestion on what I should do. – BOB Jun 27 '20 at 02:48
  • I don't remember the proper python terminology but what I mean is, there is no explicit assignment/definition of `users` anywhere in the driver. The mock needs to be mocking dynamic attribute lookups. – D. SM Jun 27 '20 at 02:51
  • do you think you could point me to am example of what you mean? @D.SM – BOB Jun 27 '20 at 03:22
  • What I would suggest is you remove all code dealing with network and just work on mocking a simple find, if you haven't successfully done this already. – D. SM Jun 27 '20 at 03:46

0 Answers0