function onChange() {
					oBinding.detachChange(onChange);
					oBinding.attachChange(done);
					setTimeout(function () {
						oBinding.checkUpdateInternal(bForceUpdate);
						//TODO return promise from above?!
					}, 0);
				}
******************************************************************************************
	["foo", false, null].forEach(function (vValue) {
		QUnit.test("checkUpdateInternal(): with vValue parameter: " + vValue, function (assert) {
			var oBinding = this.oModel.bindProperty("/absolute"),
				oPromise,
				done = assert.async();

			this.mock(this.oModel.getMetaModel()).expects("fetchUI5Type")
				.withExactArgs("/absolute")
				.returns(SyncPromise.resolve("~UI5Type~"));
			this.mock(oBinding).expects("doSetType").withExactArgs("~UI5Type~").callThrough();
			oBinding.vValue = ""; // simulate a read
			oBinding.attachChange(function () {
				assert.strictEqual(oBinding.getType(), "~UI5Type~");
				assert.strictEqual(oBinding.getValue(), vValue);
				done();
			});
			this.mock(oBinding.oCachePromise).expects("then").never();

			// code under test
			oPromise = oBinding.checkUpdateInternal(undefined, undefined, undefined, false, vValue);

			assert.ok(oPromise.isFulfilled());
			assert.strictEqual(oBinding.getValue(), vValue);

			return oPromise;
		});
	});

	//*********************************************************************************************
[null, {}].forEach((vValue) => {
	QUnit.test("checkUpdateInternal(): with vValue parameter: " + vValue, function (assert) {
		var oContext = Context.create(this.oModel, {}, "/EntitySet('foo')"),
			oBinding = this.oModel.bindProperty("property/path", oContext),
			oPromise,
			done = assert.async();

		this.mock(this.oModel.getMetaModel()).expects("fetchUI5Type")
			.withExactArgs("/EntitySet('foo')/property/path")
			.returns(SyncPromise.resolve("~UI5Type~"));
		this.mock(_Helper).expects("publicClone").exactly(vValue ? 1 : 0)
			.withExactArgs(sinon.match.same(vValue))
			.returns("~vValueClone~");
		this.mock(oBinding).expects("doSetType").withExactArgs("~UI5Type~").callThrough();
		oBinding.vValue = vValue; // simulate a read
		oBinding.attachChange(function () {
			// "change" event even for same object value (indirectly via clone)
			assert.ok(vValue, "null handled specially");
			assert.strictEqual(oBinding.getType(), "~UI5Type~");
			assert.strictEqual(oBinding.getValue(), vValue ? "~vValueClone~" : vValue);
			done();
		});
		if (!vValue) {
			done(); // no "change" event expected
		}
		this.mock(oBinding.oCachePromise).expects("then").never();

		// code under test
		oPromise = oBinding.checkUpdateInternal(undefined, undefined, undefined, false, vValue);

		assert.ok(oPromise.isFulfilled());
		assert.strictEqual(oBinding.getValue(), vValue ? "~vValueClone~" : vValue);

		return oPromise;
	});
});

	//*********************************************************************************************
	QUnit.test("checkUpdateInternal(): with vValue parameter: undefined", function (assert) {
		var oContext = Context.create(this.oModel, {}, "/EntitySet('foo')"),
			oBinding = this.oModel.bindProperty("property/path", oContext);

		oBinding.sReducedPath = "~reduced~";
		oBinding.setType(null, "any");
		oBinding.vValue = ""; // simulate a read
		this.mock(oContext).expects("fetchValue")
			.withExactArgs(oBinding.sReducedPath, sinon.match.same(oBinding))
			.returns(SyncPromise.resolve("~value~"));
		this.mock(this.oModel.getMetaModel()).expects("fetchUI5Type").never();
		this.mock(oBinding).expects("_fireChange").withExactArgs({reason : ChangeReason.Change})
			.callsFake(function () {
				assert.strictEqual(oBinding.getValue(), "~value~");
			});

		// code under test
		return oBinding.checkUpdateInternal(undefined, undefined, undefined, false, undefined)
			.then(function () {
				assert.strictEqual(oBinding.getValue(), "~value~");
			});
	});

	//*********************************************************************************************
	[{
		contextPath : "/Artists('42')",
		path : "Name##@SAP_Common.Label"
	}, {
		contextPath : undefined,
		path : "/Artists('42')/Name##@SAP_Common.Label"
	}, {
		contextPath : "/Irrelevant",
		path : "/Artists('42')/Name##@SAP_Common.Label"
	}, {
		baseContext : true,
		contextPath : "/Artists('42')",
		path : "Name##@SAP_Common.Label"
	}, {
		contextPath : "/Artists('42')",
		path : "##/@SAP_Common.Label"
	}, {
		contextPath : "/Irrelevant",
		path : "/Artists('42')/Name##@SAP_Common.Label",
		virtualContext : true
	}, {
		contextPath : "/Irrelevant",
		path : "/Artists('42')/Name##@SAP_Common.Label",
		scope : {},
		virtualContext : true
	}].forEach(function (oFixture, i) {
		QUnit.test("checkUpdateInternal, meta path, resolved, " + i, function (assert) {
			var oBinding,
				bChangeFired,
				oContext,
				oMetaContext = {},
				vValue = oFixture.virtualContext ? undefined : "Artist label";

			if (oFixture.contextPath) {
				oContext = oFixture.baseContext
					? new BaseContext(this.oModel, oFixture.contextPath)
					: Context.create(this.oModel, {/*oParentBinding