diff --git a/CHANGELOG.md b/CHANGELOG.md
index 1a4c15b8926f0311493561131634c0adf878f67b..ca3a77a2aaf04e14950f9310cbbe70d5349dc785 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -27,6 +27,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 * Tests for `BEFORE`, `AFTER`, `UNTIL`, `SINCE` keywords for query
   transaction filters
   [caosdb-server#132](https://gitlab.indiscale.com/caosdb/src/caosdb-server/-/issues/132)
+* Tests for missing obligatory Properties
+  [caosdb-server#146](https://gitlab.indiscale.com/caosdb/src/caosdb-server/-/issues/146)
+
 
 ### Changed (for changes in existing functionality)
 
diff --git a/tests/test_importance.py b/tests/test_importance.py
new file mode 100644
index 0000000000000000000000000000000000000000..afa63effa4d70b32728777d3304a09c212c318e1
--- /dev/null
+++ b/tests/test_importance.py
@@ -0,0 +1,184 @@
+#
+# This file is a part of the CaosDB Project.
+#
+# Copyright (C) 2021 IndiScale GmbH <info@indiscale.com>
+# Copyright (C) 2021 Timm Fitschen <t.fitschen@indiscale.com>
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU Affero General Public License as
+# published by the Free Software Foundation, either version 3 of the
+# License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU Affero General Public License for more details.
+#
+# You should have received a copy of the GNU Affero General Public License
+# along with this program. If not, see <https://www.gnu.org/licenses/>.
+#
+
+from pytest import raises
+import caosdb as db
+
+
+def setup():
+    teardown_module()
+
+
+def teardown_module():
+    clean = db.execute_query("FIND Test*")
+    if len(clean) > 0:
+        clean.delete()
+
+
+def test_obl_missing_error():
+    p = db.Property(name="TestOblProperty", datatype=db.TEXT).insert()
+    p_dummy = db.Property(name="TestDummyProperty", datatype=db.TEXT).insert()
+
+    rt1 = db.RecordType(name="TestRecordType1")
+    rt1.add_property(name="TestOblProperty", importance=db.OBLIGATORY)
+    rt1.insert()
+
+    # normal behaviour, should be identical to "error" level
+    rt2 = db.RecordType(name="TestRecordType2")
+    rt2.add_parent("TestRecordType1", inheritance=db.NONE)
+    rt2.add_property("TestDummyProperty")
+    with raises(db.TransactionError) as exc:
+        rt2.insert()
+    assert exc.value.errors[0].msg == "An obligatory property is missing."
+
+    # force error
+    rt2 = db.RecordType(name="TestRecordType2")
+    rt2.add_parent("TestRecordType1", inheritance=db.NONE)
+    rt2.add_property("TestDummyProperty")
+    rt2.set_flag("force-missing-obligatory", "error")
+    with raises(db.TransactionError) as exc:
+        rt2.insert()
+    assert exc.value.errors[0].msg == "An obligatory property is missing."
+
+    # warning is treated as error because "strict" flag
+    rt2 = db.RecordType(name="TestRecordType2")
+    rt2.add_parent("TestRecordType1", inheritance=db.NONE)
+    rt2.add_property("TestDummyProperty")
+    rt2.set_flag("force-missing-obligatory", "warn")
+    with raises(db.TransactionError) as exc:
+        rt2.insert(strict=True)
+    assert exc.value.errors[0].msg == (
+        "A warning occured while processing an entity with the strict flag.")
+    assert "An obligatory property is missing." in [
+        w.description for w in rt2.get_warnings()]
+
+    # insert with warning
+    rt2 = db.RecordType(name="TestRecordType2")
+    rt2.add_parent("TestRecordType1", inheritance=db.NONE)
+    rt2.add_property("TestDummyProperty")
+    rt2.set_flag("force-missing-obligatory", "warn")
+    rt2.insert()
+    assert len(rt2.get_errors()) == 0
+    assert (rt2.get_warnings()[0].description
+            == "An obligatory property is missing.")
+
+    # insert silently
+    rt3 = db.RecordType(name="TestRecordType3")
+    rt3.add_parent("TestRecordType1", inheritance=db.NONE)
+    rt3.add_property("TestDummyProperty")
+    rt3.set_flag("force-missing-obligatory", "ignore")
+    rt3.insert()
+    assert len(rt3.get_errors()) == 0
+    assert len(rt3.get_warnings()) == 0
+
+
+def test_obl_missing_parent_in_same_container():
+    p = db.Property(name="TestOblProperty", datatype=db.TEXT).insert()
+
+    rt1 = db.RecordType(name="TestRecordType1")
+    rt1.add_property(name="TestOblProperty", importance=db.OBLIGATORY)
+
+    rt2 = db.RecordType(name="TestRecordType2")
+    rt2.add_parent("TestRecordType1", inheritance=db.NONE)
+
+    c = db.Container()
+    c.extend([rt1, rt2])
+    with raises(db.TransactionError) as exc:
+        c.insert()
+    assert exc.value.errors[0].msg == "An obligatory property is missing."
+
+
+def test_obl_missing_parent_in_same_container_override():
+    """`force-missing-obligatory` flags of entities override flags of containing containers.
+    """
+    p = db.Property(name="TestOblProperty", datatype=db.TEXT).insert()
+
+    rt1 = db.RecordType(name="TestRecordType1")
+    rt1.add_property(name="TestOblProperty", importance=db.OBLIGATORY)
+
+    rt2 = db.RecordType(name="TestRecordType2")
+    rt2.add_parent("TestRecordType1", inheritance=db.NONE)
+    rt2.set_flag("force-missing-obligatory", "error")
+
+    c = db.Container()
+    c.extend([rt1, rt2])
+    with raises(db.TransactionError) as exc:
+        c.insert(flags={"force-missing-obligatory": "ignore"})
+    assert exc.value.errors[0].msg == "An obligatory property is missing."
+
+
+def test_sub_property_of_obl():
+    """If p1 <|- p2, then p2 should work for an obligatory p1.
+    """
+    p1 = db.Property(name="TestOblProperty1", datatype=db.TEXT).insert()
+    p2 = db.Property(name="TestOblProperty2", datatype=db.TEXT)
+    p2.add_parent("TestOblProperty1")
+    p2.insert()
+
+    rt1 = db.RecordType(name="TestRecordType1")
+    rt1.add_property(name="TestOblProperty1", importance=db.OBLIGATORY)
+    rt1.insert()
+
+    rt2 = db.RecordType(name="TestRecordType2")
+    rt2.add_parent("TestRecordType1", inheritance=db.NONE)
+
+    # add subtype of TestOblProperty1
+    rt2.add_property("TestOblProperty2")
+    rt2.insert()  # everything ok!
+
+
+def test_sub_property_of_obl_in_same_container():
+
+    p1 = db.Property(name="TestOblProperty1", datatype=db.TEXT).insert()
+
+    rt1 = db.RecordType(name="TestRecordType1")
+    rt1.add_property(name="TestOblProperty1", importance=db.OBLIGATORY)
+    rt1.insert()
+
+    p2 = db.Property(name="TestOblProperty2", datatype=db.TEXT)
+    p2.add_parent("TestOblProperty1")
+
+    rt2 = db.RecordType(name="TestRecordType2")
+    rt2.add_parent("TestRecordType1", inheritance=db.NONE)
+    rt2.add_property("TestOblProperty2")
+
+    c = db.Container()
+    c.extend([rt2, p2])
+    c.insert()  # everything ok!
+
+
+def test_illegal_flag_value():
+    p = db.Property(name="TestOblProperty", datatype=db.TEXT).insert()
+    p_dummy = db.Property(name="TestDummyProperty", datatype=db.TEXT).insert()
+
+    rt1 = db.RecordType(name="TestRecordType1")
+    rt1.add_property(name="TestOblProperty", importance=db.OBLIGATORY)
+    rt1.insert()
+
+    rt2 = db.RecordType(name="TestRecordType2")
+    rt2.add_parent("TestRecordType1", inheritance=db.NONE)
+    rt2.add_property("TestDummyProperty")
+    rt2.set_flag("force-missing-obligatory", "illegal!!!!")
+    with raises(db.TransactionError) as exc:
+        rt2.insert()
+    # default behavior + warning
+    assert exc.value.errors[0].msg == "An obligatory property is missing."
+    assert "Illegal value for flag 'force-missing-obligatory'." in [
+        w.description for w in rt2.get_warnings()]